/*
 +----------------------------------------------------------------------
 + Title        : websocket
 + Author       : huwl
 + Version      : 1.0.0
 + Initial-Time : 2023-08-10
 + Last-time    : 这个文件最后修改的时间 + 修改人的名称
 + Desc         : websocket操作工具
 +----------------------------------------------------------------------
*/

import type { Message } from "@/types/chat"
import { nextTick, ref } from "vue"
import dayjs from 'dayjs'


// 指定url
// const url = ref<string>('ws://127.0.0.1:7272?uid='+ fromUid.value +'&username=杀戮天君'+ '&group=trident')

const url = ref<string>('')

// 定义WebSocket
export const websocket = ref<WebSocket>()

// 定义消息列表
export const messageList = ref<Message[]>([])

// 当前重连次数
const retries = ref(0)

// 重连间隔时间（毫秒）
const reconnectInterval = ref(3000);

// 最大重连次数
const maxRetries = ref(5);

// 客户端的心跳周期应该要比服务端小一些
// 心跳间隔为30秒
const heartbeatInterval = 30 * 1000;

// 心跳超时时间为50秒
const heartbeatTimeout = 60 * 1000;

// 心跳间隔Id
const heartbeatIntervalId = ref()

// 心跳超时Id
const heartbeatTimeoutId = ref()

// 设置URL
export const setUrl = (value: string) => {
    url.value = value
}

// ------------- 初始化 websocket 开始 -------------
export const initWebSocket = () => {
    // https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket
    websocket.value = new WebSocket(url.value)

    // 监听连接
    websocket.value.onopen = (event) => {
        console.log('WebSocket connection opened:', event)
        
        // 心跳检测
        startHeartbeat();
    }

    // 监听消息
    websocket.value.onmessage = async (event) => {
        console.log('WebSocket onmessage:', event)
        console.log(event.data);
        const data = JSON.parse(event.data);
        console.log('data =', data);
        switch (data.event_type) {
            case 'sendToUidDemo':
                messageList.value.push(data)
                break;
            case 'ping':
                console.log('发送响应服务端心跳');
                websocket.value?.send(JSON.stringify({event_type: 'pong', create_time: dayjs().format('YYYY-MM-DD HH:mm:ss')})); // 发送响应服务端心跳
                break;
            case 'pong':
                console.log('来自服务端的心跳反馈');
                
                // 重置心跳超时定时器
                clearTimeout(heartbeatTimeoutId.value);
                break;
            default:
                break;
        }

        // 始终显示新一条消息
        await nextTick()
        window.scrollTo(0, document.body.scrollHeight)
    }

    // 监听错误
    websocket.value.onerror = function(error) {
        console.error('WebSocket error observed =', error);
    };

    // 监听关闭
    websocket.value.onclose = function(event) {
        console.log('WebSocket closed =', event);

        // 连接关闭时清除定时器
        clearInterval(heartbeatIntervalId.value);
        clearTimeout(heartbeatTimeoutId.value);

        // 断线重连
        reconnect(reconnectInterval.value, maxRetries.value)
        // setTimeout(initWebSocket, 1000); // 1秒后尝试重新连接
    };
}
// ------------- 初始化 websocket 结束 -------------



// ---------------- 重新连接功能开始 ----------------
const reconnect = (intervalTime: number, reconnectCount: number) => {
    console.log('retries =', retries.value)
    console.log('reconnectCount =', reconnectCount)
    
    if (retries.value < reconnectCount) {
        console.log('重连');
        setTimeout(initWebSocket, intervalTime)
        retries.value++
    }
}
// ---------------- 重新连接功能结束 ----------------



// ---------------- 心跳检测功能开始 ----------------
const startHeartbeat = () => {
    heartbeatIntervalId.value = setInterval(function() {
        websocket.value?.send(JSON.stringify({event_type: 'ping', create_time: dayjs().format('YYYY-MM-DD HH:mm:ss')})); // 发送心跳包

        // 重置心跳超时定时器
        clearTimeout(heartbeatTimeoutId.value);
        heartbeatTimeoutId.value = setTimeout(function() {
            console.log('Heartbeat timeout, closing the connection.');
            websocket.value?.close(); // 超时未收到响应，关闭连接
            // 这里可以添加重新连接的逻辑
        }, heartbeatTimeout);
    }, heartbeatInterval);
}
// ---------------- 心跳检测功能开始 ----------------



// -------------- 处理关闭连接功能开始 --------------
export const handleCloseConn = () => {
    retries.value = 5
    websocket.value?.close(1000, 'Done')
}
// -------------- 处理关闭连接功能结束 --------------